package ricky.scene
{
	import com.adobe.utils.AGALMiniAssembler;
	import com.adobe.utils.PerspectiveMatrix3D;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Stage3D;
	import flash.display3D.Context3D;
	import flash.display3D.Context3DProgramType;
	import flash.display3D.Context3DTextureFormat;
	import flash.display3D.Context3DVertexBufferFormat;
	import flash.display3D.IndexBuffer3D;
	import flash.display3D.Program3D;
	import flash.display3D.VertexBuffer3D;
	import flash.display3D.textures.Texture;
	import flash.events.Event;
	import flash.geom.Matrix;
	import flash.geom.Matrix3D;
	import flash.geom.PerspectiveProjection;
	import flash.geom.Point;
	import flash.geom.Vector3D;
	import flash.system.ApplicationDomain;
	import flash.utils.Dictionary;
	import flash.utils.getTimer;
	
	import ricky.loader.Request;
	

	/**
	 * 3d加速场景地毯层
	 */
	public class Stage3DMapLayout extends MapLayout
	{
		public function Stage3DMapLayout()
		{
			super();
			this.addEventListener(Event.ADDED_TO_STAGE,init);
			textures=new Dictionary();
		}
		
		/**  透视 */
		public function get projectionTransform():PerspectiveMatrix3D
		{
			if(!_projectionTransform)
			{
				_projectionTransform = new PerspectiveMatrix3D();
				var aspect:Number =1;// stageWidth/stageHeight;
				var zNear:Number =0.1;
				var zFar:Number = 100;
				var fov:Number = 45*Math.PI/180;
				_projectionTransform.perspectiveFieldOfViewLH(fov, aspect, zNear, zFar);
			}
			return _projectionTransform;
		}

		/**
		 * 改变大小
		 */
		override public function resize(width:Number,height:Number,x:Number=NaN,y:Number=NaN):void
		{
//			_context3d.configureBackBuffer(width,height,2);
			this.init(null);
			this.createModel(null);
		}
		
		/**
		 * 设置地图格子信息用来创建地图数据
		 */
		override public function setGridInfo(gridW:Number,gridH:Number):void
		{
			super.setGridInfo(gridW,gridH);
			createModel(null);
		}
		
		/**
		 *绘制缓冲区
		 */
		override public function loadResource(gx:int,gy:int,gwidth:int,gheight:int):void
		{
			
			var vtsx:int=gx+gwidth;
			var vtsy:int=gy+gheight;
			for(var i:int=gx; i<=vtsx;i++)
			{
				for(var j:int=gy;j<=vtsy;j++)
				{
					if(!textures[i+","+j])
						loadTile(i,j);
				}
			}	
		}
		
		/**
		 * 移动
		 */
		override public function moveing():void
		{
			if(!_initialized)
				return;
			
			if(!model)
				createModel(null);

			if(this.parent && model)
			{
				var camera:Camera=Scene(parent).camera;
				model.identity();
				model.appendTranslation(-1,1,0);//地图偏移
				model.appendTranslation(-camera.x/camera.width*2,camera.y/camera.height*2,0);//运动
				this.render(camera);
			}
		}
				
		/////////////////////////////////////////////////////////////////////////////
		// ******************私有***********************
		/////////////////////////////////////////////////////////////////////////////
		
		/**
		 * 初始化3d环境
		 */
		protected function init(e:Event):void
		{
			this.removeEventListener(Event.ADDED_TO_STAGE,init);
			
			var stage3D:Stage3D=this.stage.stage3Ds[0];
			if(stage3D)
			{
				stage3D.addEventListener(Event.CONTEXT3D_CREATE,context3DCreate);
				stage3D.requestContext3D();
			}
			
		}
		
		/**
		 * 初始化3d场景，创建shader
		 */
		protected function context3DCreate(e:Event):void
		{
			_context3d=Stage3D(e.target).context3D;
			var s:Scene=this.parent as Scene;
			stageWidth=s.camera.width;
			stageHeight=s.camera.height;
			_context3d.configureBackBuffer(stageWidth,stageHeight,4,false);
//			_context3d.enableErrorChecking=true;
			mapprograme=_context3d.createProgram();
			vertexShader=new AGALMiniAssembler();
			vertexShader.assemble(Context3DProgramType.VERTEX,vertexAgal);
			fragmentShader=new AGALMiniAssembler();
			fragmentShader.assemble(Context3DProgramType.FRAGMENT,fragmentAgal);
			mapprograme.upload(vertexShader.agalcode,fragmentShader.agalcode);
			
			_context3d.setProgram(mapprograme);
			
			_initialized=true;
		}
		
		/**
		 * 根据地图信息创建模型
		 */
		protected function createModel(e:Event):void
		{
			if(_context3d)
			{
				var s:Scene=this.parent as Scene;
				var camera:Camera=s.camera;
				
				var px:Number=camera.gridWidth/(camera.width)*2;//x坐标比例
				var py:Number=camera.gridHeight/(camera.height)*2;//y坐标比例
				
				var puvx:Number=0.68; //camera.gridWidth/512;//0.68359375
				var puvy:Number=0.6800;//camera.gridHeight/512;
				
				maxX=camera.xGridCount;
				var maxY:int=camera.yGridCount;
				var l:int,perdata:int;
				var vectors:Vector.<Number>=new Vector.<Number>();//顶点集合
				
				maxIndex=maxY*maxX;//模型正方形数目
				var indexs:Vector.<uint>=new Vector.<uint>();
				var col:int=0,row:int=0,tmp:int;
				var p1:Number,p2:Number,p3:Number,p4:Number;
				var vectorRow:Vector.<Vector3D>=new Vector.<Vector3D>();
				var vector3d:Vector3D;
				//顶点
				for(var j:int=0;j<=maxY;j++)
				{
					for(var i:int=0; i<=maxX;i++)
					{
						
						vector3d=new Vector3D();
						vector3d.x=i*px;
						vector3d.y=-j*py;
						vectorRow.push(vector3d);
					}
				}
				
				//索引
				var v1:Vector3D,v2:Vector3D,v3:Vector3D,v4:Vector3D,bindex:int;
				for(var i:int=0;i<maxIndex;i++)
				{
					if(i % maxX ==0 && i!=0)
					{
						row++;//换行
					}
//					p1=col*px;p2=(col+1)*px;
//					p3=-row*py;p4=(-row-1)*py;
					
					bindex=i+row;
					v1=vectorRow[bindex]; //0,0
					v2=vectorRow[bindex+1]; //1,0
					v3=vectorRow[bindex+maxX+1];//0,1
					v4=vectorRow[bindex+maxX+2];//1,1

					//画六个顶点(x,y,z					u,v);
//					vectors.push(p1,p3,0, 		0,0	);			//0,0
//					vectors.push(p2,p3,0, 	puvx,0);		//1,0
//					vectors.push(p1,p4,0, 	0,puvy);		//0,1
//					
//					vectors.push(p2,p3,0, 	puvx,0);	//1,0
//					vectors.push(p1,p4,0, 	0,puvy);		//0,1
//					vectors.push(p2,p4,0, 	puvx,puvy);	//1,1
					
					vectors.push(v1.x,v1.y,0, 		0,0	);			//0,0
					vectors.push(v2.x,v2.y,0, 	puvx,0);		//1,0
					vectors.push(v3.x,v3.y,0, 	0,puvy);		//0,1
					
					vectors.push(v2.x,v2.y,0, 	puvx,0);	//1,0
					vectors.push(v3.x,v3.y,0, 	0,puvy);		//0,1
					vectors.push(v4.x,v4.y,0, 	puvx,puvy);	//1,1
					
					tmp=i*6;

					indexs.push(tmp,tmp+1,tmp+2,tmp+3,tmp+4,tmp+5);
				}
				
				
				/////////////////////////////////////// 顶点////////////////////////////
				l=vectors.length;
				perdata=5;
				vertexbuffer=_context3d.createVertexBuffer(l/perdata,perdata);
				vertexbuffer.uploadFromVector(vectors,0,l/perdata);				
				
				/////////////////////////////////////// 索引////////////////////////////

				l=indexs.length;
				indexbuffer=_context3d.createIndexBuffer(l);
				indexbuffer.uploadFromVector(indexs,0,l);
				
				/////////////////////// 材质 //////////////////////
				texture=_context3d.createTexture(512,512,Context3DTextureFormat.BGRA,true);
				
				texture.uploadFromBitmapData(new BitmapData(512,512,false,0x00000f));
				
				//////////////////////////矩阵//////////////////////
				finalTransform=new Matrix3D();
				model=new Matrix3D();
			}
		}
		
		override protected function onComplete(e:Request):void
		{			
			var i:int=0,j:int=0;
			var s:Array=e.head.split(",");
			i=int(s[0]);
			j=int(s[1]);
			
			var x1:Number=i*gridWidth;
			var y1:Number=j*gridHeight;
			var bmp:Bitmap=e.data;
			
			if(!_mapLoadDir[e.key])
				_mapLoadDir[e.key]=bmp;
			
			var bitMap:Bitmap=_mapLoadDir[e.key];
			
			uploadtexture(e.key,bitMap.bitmapData);
			
			delete _mapLoadDir[e.key];
		}
		
		/**
		* 加载制定坐标格子的资源块
		*/
		override protected function loadTile(i:int,j:int):void
		{
			super.loadTile(i,j);
		}
		
		/**
		 * 上传材质O
		 */
		protected function uploadtexture(key:String,bitmapdata:BitmapData):void
		{
			if(_context3d)
			{
				var textu:Texture=this.textures[key];
				if(!textu)
				{
//					var bit:BitmapData=new BitmapData(513,513,false,0xffffff);
					textu=_context3d.createTexture(512,512,Context3DTextureFormat.BGRA,false);
//					bit.copyPixels(bitmapdata,bitmapdata.rect,new Point(0,0));
					textu.uploadFromBitmapData(bitmapdata);
					textures[key]=textu;
					bitmapdata.dispose();

				}
				this.moveing();
			}
		}
		
		/**
		 * 输出地图
		 */
		protected function render(camera:Camera):void
		{
			if(_context3d)
			{
				var gx:int=camera.gridX;
				var gy:int=camera.gridY;
				var gwidth:int=camera.gridBufferWidth+gx;
				var gheight:int=camera.gridBufferHeight+gy;
				
				this._context3d.clear();
				_context3d.setProgram(mapprograme);
				_context3d.setVertexBufferAt(0,vertexbuffer,0,Context3DVertexBufferFormat.FLOAT_3);
				_context3d.setVertexBufferAt(1,vertexbuffer,3,Context3DVertexBufferFormat.FLOAT_2);

				finalTransform.identity();
				finalTransform.appendTranslation(0,0,2);
//				finalTransform.appendRotation(flash.utils.getTimer()/30,Vector3D.X_AXIS);				
				finalTransform.append(model);
				finalTransform.append(projectionTransform);
				_context3d.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX,0,finalTransform,true);

				var key:String="",bi:int;
				for(var j:int=gy;j<=gheight;j++)
				{
					for(var i:int=gx; i<=gwidth;i++)
					{
						key=i+","+j;
						tmptexture=this.textures[key];
						if(!tmptexture)
							tmptexture=this.texture;
						_context3d.setTextureAt(0,tmptexture);
						bi=j*this.maxX+i;//开始正方形索引
						if(bi>maxIndex-1)
							continue;
						_context3d.drawTriangles(indexbuffer,bi*6,2);
					}
				}	
				_context3d.present();
			}
		}

		//成员变量
		
		////////////////////
		private var maxX:int=1;
		/////////////////////////////////////////
		//用于渲染
		////////////////////////////////////////
		private var _context3d:Context3D;
		/** 上传程序*/
		private var mapprograme:Program3D;//
		/** 顶点agal*/
		private var vertexAgal:String="m44 op, va0, vc0 \n" +    //copy position to output 
			"mov v0, va1"; //copy color to varying variable v0
		/** 片段agal*/
		private var fragmentAgal:String="tex ft0, v0, fs0 <2d,linear,nomip> \nmov oc, ft0 \n";//"tex ft0, v0, fs0 <2d,repeat,nomip>\n" +
		//"mov oc, ft0\n";//fto
		/** 顶点着色器*/
		private var vertexShader:AGALMiniAssembler;
		/** 片段着色器*/
		private var fragmentShader:AGALMiniAssembler;
		/** 顶点集合 */
		private var vertexbuffer:VertexBuffer3D;
		/** 索引集合 */
		private var indexbuffer:IndexBuffer3D;
		/** 默认材质  */
		private var texture:Texture;
		/** 零时材质  */
		private var tmptexture:Texture;
		/** 材质集合 */
		private var textures:Dictionary=new Dictionary();
		/**传入矩阵*/
		private var finalTransform:Matrix3D;
		/** 地图模型移动矩阵 */
		private var model:Matrix3D;
		/**  最大索引数 */
		private var maxIndex:int;
		//透视
		private var _projectionTransform:PerspectiveMatrix3D;
		
		private var stageWidth:Number;
		private var stageHeight:Number;
	}
}